package com.jrx.anytxn.transaction.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.mapper.ext.ExtCmCustomerSecondLevelMapper;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.dto.billCompare.TlThirdBillDetailRes;
import com.jrx.anytxn.param.entity.TlBillTransCompareDetail;
import com.jrx.anytxn.param.entity.TlThirdBillDetail;
import com.jrx.anytxn.param.service.billCompare.ITlThirdBillDetailService;
import com.jrx.anytxn.transaction.bean.DealBillDetailBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.dto.loan.CancelOrderQueryRes;
import com.jrx.anytxn.transaction.dto.loan.CancelOrderRep;
import com.jrx.anytxn.transaction.dto.loan.RecordGlInterfaceReq;
import com.jrx.anytxn.transaction.dto.payment.RefundReq;
import com.jrx.anytxn.transaction.dto.payment.RefundRes;
import com.jrx.anytxn.transaction.entity.AmLoanAccountInfo;
import com.jrx.anytxn.transaction.entity.AmLoanMainInfo;
import com.jrx.anytxn.transaction.entity.TlGlInterfaceInfo;
import com.jrx.anytxn.transaction.entity.TlMistakeLog;
import com.jrx.anytxn.transaction.entity.TlPaymentLog;
import com.jrx.anytxn.transaction.handler.ILoanHandler;
import com.jrx.anytxn.transaction.handler.IPaymentHandler;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanAccountInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanMainInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlGlInterfaceInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlMistakeLogMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlPaymentLogMapper;
import com.jrx.anytxn.transaction.service.IGlInterfaceService;
import com.jrx.anytxn.transaction.service.IMistakeBillDetailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author llk
 * @Date 3:02 下午 星期六 2021/7/17
 **/
@Service
public class MistakeBillDetailService implements IMistakeBillDetailService {

    private static final Logger logger = LoggerFactory.getLogger(MistakeBillDetailService.class);

    @Resource
    private ILoanHandler loanHandler;
    @Resource
    private ITlThirdBillDetailService tlThirdBillDetailService;
    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;
    @Resource
    private ExtAmLoanAccountInfoMapper extAmLoanAccountInfoMapper;
    @Resource
    private ExtCmCustomerSecondLevelMapper extCmCustomerSecondLevelMapper;
    @Resource
    private IPaymentHandler paymentHandler;
    @Resource
    private ExtTlGlInterfaceInfoMapper extTlGlInterfaceInfoMapper;
    @Resource
    private IGlInterfaceService glInterfaceService;
    @Resource
    private ExtTlPaymentLogMapper extTlPaymentLogMapper;
    @Resource
    private ExtTlMistakeLogMapper extTlMistakeLogMapperl;

    @Override
    public TxnPage<TlThirdBillDetailRes> findAllPageByTenantId(Integer pageNum, Integer pageSize, String tenantId) throws TxnException {
        return tlThirdBillDetailService.findAllPageByTenantId(pageNum, pageSize, tenantId);
    }

    @Override
    public void dealMistakeRecord(DealBillDetailBean dealBillDetailBean, String nickName) throws Exception {

        TlBillTransCompareDetail compareDetail = tlThirdBillDetailService.findById(dealBillDetailBean.getTenantId(),
                dealBillDetailBean.getThirdChannel(), dealBillDetailBean.getId());
        Assert.notNull(compareDetail, TxnRespCode.NO_DATA.getFormatUserTips());

        TlThirdBillDetail tlThirdBillDetail = tlThirdBillDetailService.findByThirdSeq(compareDetail.getTenantId(),
                compareDetail.getThirdChannel(), compareDetail.getSeqNo(), compareDetail.getBillType());
        Assert.notNull(tlThirdBillDetail, TxnRespCode.NO_DATA.getFormatUserTips());
        String desc = nickName + "_已处理" + "_" + DateUtils.format(new Date(), DateUtils.DATETIME_PATTERN);
        if (Constant.TRANSACTION_TYPE_TK.equals(compareDetail.getBillType())) {
            refund(compareDetail, tlThirdBillDetail, desc);
        }
        if (Constant.TRANSACTION_TYPE_CX.equals(compareDetail.getBillType())) {
            cancelOrder(compareDetail, tlThirdBillDetail, desc);
        }
        if (Constant.TRANSACTION_TYPE_CZ.equals(compareDetail.getBillType())) {
            cancelOrder(compareDetail, tlThirdBillDetail, desc);
        }

    }

    /**
     * 重新取消
     *
     * @param compareDetail
     * @param tlThirdBillDetail
     */
    private void cancelOrder(TlBillTransCompareDetail compareDetail, TlThirdBillDetail detail, String desc) throws Exception {

        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectBySeqNoAndTenantId(detail.getOrgThirdSeq(), TransBizConstant.LOAN_TYPE_4, detail.getThirdChannel(), detail.getTenantId());
        //消费超时 发起撤销
        if (Objects.isNull(amLoanMainInfo)) {
            tlThirdBillDetailService.updateCompareStatus(compareDetail.getTenantId(), Constant.COMPARE_FLAG_1, desc, compareDetail.getId());
            return;
        }

        AmLoanAccountInfo amLoanAccountInfo = extAmLoanAccountInfoMapper.selectByLoanId(amLoanMainInfo.getLoanId(), amLoanMainInfo.getCustomerId(), amLoanMainInfo.getTenantId());

        if (TransBizConstant.ACCOUNT_STATUS_9.equals(amLoanAccountInfo.getAccountStatus())) {
            tlThirdBillDetailService.updateCompareStatus(compareDetail.getTenantId(), Constant.COMPARE_FLAG_1, desc, compareDetail.getId());
            return;
        }

        CmCustomerSecondLevel cmCustomerSecondLevel = extCmCustomerSecondLevelMapper.selectByCustomerIdAndChannel(amLoanMainInfo.getCustomerId(), amLoanMainInfo.getChannel(), amLoanMainInfo.getTenantId());
        Assert.notNull(cmCustomerSecondLevel, TxnRespCode.NO_DATA.getFormatUserTips());

        CancelOrderRep cancelOrderRep = new CancelOrderRep();
        cancelOrderRep.setTenantId(amLoanMainInfo.getTenantId());
        cancelOrderRep.setChannel(amLoanMainInfo.getChannel());
        cancelOrderRep.setThirdChannel(amLoanMainInfo.getThirdChannel());
        cancelOrderRep.setSeqNo(detail.getThirdSeq());
        cancelOrderRep.setUserId(cmCustomerSecondLevel.getUserId());
        cancelOrderRep.setLoanId(amLoanMainInfo.getLoanId());
        CancelOrderQueryRes cancelOrderQueryRes = Optional.ofNullable(loanHandler.cancelOrderHandle(cancelOrderRep)).orElseThrow(() -> new TxnException(TxnRespCode.ERROR.getFormatUserTips()));
        Assert.isTrue(TransBizConstant.GATEWAY_DEAL_SUC.equals(cancelOrderQueryRes.getSunStatus()), TxnRespCode.ERROR.getFormatUserTips());

        tlThirdBillDetailService.updateCompareStatus(compareDetail.getTenantId(), Constant.COMPARE_FLAG_1, desc, compareDetail.getId());

    }

    /**
     * 重新退款
     *
     * @param compareDetail
     * @param tlThirdBillDetail
     */
    private void refund(TlBillTransCompareDetail compareDetail, TlThirdBillDetail detail, String desc) throws Exception {

        AmLoanMainInfo amLoanMainInfo = extAmLoanMainInfoMapper.selectBySeqNoAndTenantId(detail.getOrgThirdSeq(), TransBizConstant.LOAN_TYPE_4, detail.getThirdChannel(), detail.getTenantId());
        Assert.notNull(amLoanMainInfo, TxnRespCode.NO_DATA.getFormatUserTips());

        TlPaymentLog tlPaymentLog = extTlPaymentLogMapper.selectByPayIdAndPaymentType(detail.getThirdSeq(), TransBizConstant.REPAYMENT_TYPE_REFUND, detail.getThirdChannel(), detail.getTenantId());

        if (Objects.nonNull(tlPaymentLog)) {

            TlMistakeLog tlMistakeLog = extTlMistakeLogMapperl.selectMistakeBySeqNo(tlPaymentLog.getSeqNo(), tlPaymentLog.getCustomerId(), tlPaymentLog.getTenantId());
            if (Objects.nonNull(tlMistakeLog)) {
                logger.info("退款差异已进差错表无需处理 ：{}", detail.getThirdSeq());
                tlThirdBillDetailService.updateCompareStatus(compareDetail.getTenantId(), Constant.COMPARE_FLAG_1, desc, compareDetail.getId());
                return;
            }

            boolean sign = TransBizConstant.PAYMENT_LOG_SUM_STATUS_T.equals(tlPaymentLog.getSumStatus()) || TransBizConstant.PAYMENT_LOG_SUM_STATUS_S.equals(tlPaymentLog.getSumStatus());
            if (sign) {
                logger.info("退款差异对应的还款流水已经成功无需处理 ：{}", detail.getThirdSeq());
                tlThirdBillDetailService.updateCompareStatus(compareDetail.getTenantId(), Constant.COMPARE_FLAG_1, desc, compareDetail.getId());
                return;
            }
        }

        CmCustomerSecondLevel cmCustomerSecondLevel = extCmCustomerSecondLevelMapper.selectByCustomerIdAndChannel(amLoanMainInfo.getCustomerId(), amLoanMainInfo.getChannel(), amLoanMainInfo.getTenantId());
        Assert.notNull(cmCustomerSecondLevel, TxnRespCode.NO_DATA.getFormatUserTips());
        List<TlGlInterfaceInfo> gls = extTlGlInterfaceInfoMapper.getAllTlGlInterfaceInfo(amLoanMainInfo.getTenantId(), amLoanMainInfo.getCustomerId(), amLoanMainInfo.getLoanId());

        BigDecimal marketingFeeAmt = gls.stream().filter(g -> TransBizConstant.TXN_CODE_MARKETING_FEE.equals(g.getTxnCode())).map(TlGlInterfaceInfo::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal marketingRecoveryFeeAmt = gls.stream().filter(g -> TransBizConstant.TXN_CODE_MARKETING_RECOVERY_FEE.equals(g.getTxnCode())).map(TlGlInterfaceInfo::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal recoveryAmount = BigDecimal.ZERO;

        BigDecimal recordedAmount = BigDecimal.ZERO;

        BigDecimal recordedTranAnt = BigDecimal.ZERO;

        BigDecimal tranAnt = detail.getTransactionAmount();
        logger.info("arketingFeeAmt : {}  marketingRecoveryFeeAmt:{}", marketingFeeAmt, marketingRecoveryFeeAmt);

        if (marketingFeeAmt.compareTo(marketingRecoveryFeeAmt) > 0) {
            recoveryAmount = marketingFeeAmt.subtract(marketingRecoveryFeeAmt);
        }

        if (tranAnt.compareTo(recoveryAmount) <= 0) {
            recordedAmount = recordedAmount.add(tranAnt);
        }

        if (tranAnt.compareTo(recoveryAmount) > 0) {
            recordedTranAnt = tranAnt.subtract(recordedAmount);

        }
        logger.info("recordedAmount : {}  recordedTranAnt:{}", recordedAmount, recordedTranAnt);

        if (BigDecimal.ZERO.compareTo(recordedAmount) < 0) {
            RecordGlInterfaceReq recordGlInterfaceReq = new RecordGlInterfaceReq();
            recordGlInterfaceReq.setTenantId(amLoanMainInfo.getTenantId());
            recordGlInterfaceReq.setChannel(amLoanMainInfo.getChannel());
            recordGlInterfaceReq.setThirdChannel(amLoanMainInfo.getThirdChannel());
            recordGlInterfaceReq.setSeqNo(detail.getThirdSeq());
            recordGlInterfaceReq.setUserId(cmCustomerSecondLevel.getUserId());
            recordGlInterfaceReq.setLoanId(amLoanMainInfo.getLoanId());
            recordGlInterfaceReq.setTransactionCode(TransBizConstant.TXN_CODE_MARKETING_RECOVERY_FEE);
            glInterfaceService.buildTlGlInterfaceInfo(recordGlInterfaceReq);
        }

        if (BigDecimal.ZERO.compareTo(recordedTranAnt) < 0) {
            RefundReq refundReq = new RefundReq();
            refundReq.setTenantId(amLoanMainInfo.getTenantId());
            refundReq.setChannel(amLoanMainInfo.getChannel());
            refundReq.setThirdChannel(amLoanMainInfo.getThirdChannel());
            refundReq.setSeqNo(detail.getThirdSeq());
            refundReq.setUserId(cmCustomerSecondLevel.getUserId());
            refundReq.setOrigSeqNo(detail.getOrgThirdSeq());
            refundReq.setRefundAmount(recordedTranAnt);
            paymentHandler.refund(refundReq);
        }

        tlThirdBillDetailService.updateCompareStatus(compareDetail.getTenantId(), Constant.COMPARE_FLAG_1, desc, compareDetail.getId());
    }

}
